<template>
  <ul class="ipAddress" :style="`width: ${width}px`">
    <li v-for="(item, index) in ipAddress" :key="index">
      <input
        ref="ipInputRef"
        v-model="item.value"
        type="text"
        class="ipInputClass"
        :style="`width: ${width / 4}px`"
        @input="checkIpVal(item)"
        @keyup="turnIpPosition(item, index, $event)"
      />
      <div></div>
    </li>
  </ul>
</template>

<script>
import { ref, watch, onMounted } from 'vue'

export default {
  props: {
    modelValue: {
      type: String,
      default: ''
    },
    width: {
      type: Number,
      default: 300
    },
    clearFlag: { type: Boolean, default: false }
  },
  setup(props, { emit }) {
    const ipAddress = ref([{ value: '' }, { value: '' }, { value: '' }, { value: '' }])

    const ipInputRef = ref(null)

    onMounted(() => {
      if (props.modelValue) {
        const values = props.modelValue.split('.')
        ipAddress.value = values.map((value) => ({ value }))
      }
    })

    watch(
      ipAddress,
      () => {
        const str = ipAddress.value.map((item) => item.value).join('.')
        emit('update:modelValue', str)
      },
      { deep: true }
    )

    watch(
      () => props.clearFlag,
      (newVal) => {
        if (newVal) {
          ipAddress.value = [{ value: '' }, { value: '' }, { value: '' }, { value: '' }]
        }
      }
    )

    const formatter = (val) => {
      let value = val.toString()
      if (value.length === 2) {
        value = '0' + value
      } else if (value.length === 1) {
        value = '00' + value
      } else if (value.length === 0) {
        value = '000'
      }
      return value
    }

    const checkIpVal = (item) => {
      let val = item.value
      val = val.toString().replace(/[^0-9]/g, '')
      val = parseInt(val, 10)
      if (isNaN(val)) {
        val = ''
      } else {
        val = val < 0 ? 0 : val
        val = val > 255 ? 255 : val
      }
      item.value = val
    }

    const turnIpPosition = (item, index, event) => {
      const e = event || window.event
      if (e.keyCode === 37) {
        if (index !== 0 && e.currentTarget.selectionStart === 0) {
          ipInputRef.value[index - 1].focus()
        }
      } else if (e.keyCode === 39) {
        if (index !== 3 && e.currentTarget.selectionStart === item.value.toString().length) {
          ipInputRef.value[index + 1].focus()
        }
      } else if (e.keyCode === 8) {
        if (index !== 0 && item.value === '') {
          ipInputRef.value[index - 1].focus()
        }
      } else if (e.keyCode === 13 || e.keyCode === 32 || e.keyCode === 190 || e.keyCode === 110) {
        if (index !== 3) {
          ipInputRef.value[index + 1].focus()
        }
      } else if (item.value.toString().length === 3) {
        if (index !== 3) {
          ipInputRef.value[index + 1].focus()
        }
      }
    }

    return {
      ipAddress,
      formatter,
      checkIpVal,
      turnIpPosition,
      ipInputRef
    }
  }
}
</script>

<style scoped>
.ipAddress {
  display: flex;
  border-bottom: 1px solid black;
  border-radius: 4px;
  height: 30px;
  padding-inline-start: 0px;
}
.ipAddress li {
  position: relative;
  height: 30px;
  margin: 0;
  list-style-type: none;
}
.ipInputClass {
  font-size: 1rem;
  color: black;
  border: none;
  height: 23px;
  text-align: center;
  background: transparent;
}
.ipAddress li div {
  position: absolute;
  bottom: 8px;
  right: 0;
  border-radius: 50%;
  background: black;
  width: 4px;
  height: 4px;
}
.ipAddress li:last-child div {
  display: none;
}
.ipAddress input:focus {
  outline: none;
}
</style>
